package world.criver.h50909.construct;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import world.criver.CSqlite;
import world.criver.h50909.data.daSqlite;
import world.criver.h50909.entity.entEquipmentInfo;
import world.criver.h50909.entity.entEquipmentState;
import world.criver.h50909.entity.entEquipmentSummary;
import world.criver.h50909.function.funHttp;
import world.criver.h50909.properties.proConfig;
import world.criver.h50909.tool.toolEquipmentInfo;
import world.criver.h50909.tool.toolEquipmentState;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.StringReader;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;

@Component
public class constructSql {
    @Autowired
    private proConfig config;
    @Autowired
    private toolEquipmentInfo toolEquipmentInfo;
    @Autowired
    private toolEquipmentState toolEquipmentState;
    private static HashMap<String,ArrayList<entEquipmentState>> data=new HashMap<>();
    @PostConstruct
    public void connectSqlite(){
        daSqlite.tool=new CSqlite(new File(config.getSql_path()).getAbsolutePath());
        daSqlite.tool.connect();
    }
    @PostConstruct
    public void timerTask(){
        new Timer().schedule(new updateEquipmentState(),new Date(), config.getEquipment_update_interval_ms());
        new Timer().schedule(new saveOldState(),10_000);
    }

    /**
     * 每次启动和每日 0:10 分保存前日数据
     */
    private class saveOldState extends TimerTask{

        @Override
        public void run() {
            LocalDate today=LocalDate.now();
            List<entEquipmentSummary> as=toolEquipmentInfo.querySummaryList();
            for(entEquipmentSummary e:as)toolEquipmentState.saveYesterdayData(e.getName(),today);
            long now_t=System.currentTimeMillis();
            long tomorrow_t=0;
            today=today.plusDays(1);
            tomorrow_t=today.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli();
            new Timer().schedule(new saveOldState(),tomorrow_t-now_t);
        }
    }
    /**
     * 每5秒获取一下设备信息
     */
    private class updateEquipmentState extends TimerTask {
        @Override
        public void run() {
            List<entEquipmentInfo> ds=toolEquipmentInfo.queryList();
            if(ds==null)return;
            long t=System.currentTimeMillis();
            for(entEquipmentInfo info:ds) {
                Thread.startVirtualThread(() -> {
                    addTestState(info.getName());
//                    funHttp http = new funHttp();
//                    String jn = null;
//                    if (info.getMethod().equals("GET"))jn= http.get(info.getProtocol()+info.getUrl(),null);
//                    else jn= http.post(info.getProtocol()+info.getUrl(),null,null);
//                    if(jn==null)return;
//                    Document document=StringToXml(jn);
//                    byte alarm=queryJsonForExist(info.getAlarmKey(),document);
//                    byte process=queryJsonForExist(info.getProcessKey(),document);
//                    byte await=process==1?0:queryJsonForExist(info.getAwaitKey(),document);
//                    String program=queryJsonForProgram(info.getProgramKey(),document);
//                    String speed=queryJsonForProgram(info.getSpeedKey(),document);
//                    toolEquipmentState.add(new entEquipmentState(info.getName(),t,alarm,process,await,program,speed));
                });
            }
        }
    }
    private Document StringToXml(String body){
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            return builder.parse(new InputSource(new StringReader(body)));
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
    private byte queryJsonForExist(String key,Document body){
        try {
            NodeList nl=body.getElementsByTagName("Streams");
            if(nl.getLength()==0)return 0;
            JsonNode jnn = new ObjectMapper().readTree(key);
            byte a = -1;
            for(int i=0;i<jnn.size();i++){
                String k=jnn.get(i).get("key").asText();
                String v=queryName(k,nl.item(0));
                if(v==null)continue;
                boolean none=v.isEmpty();
                if(!none) {
                    String[] ns = config.getNone().split(",");
                    for (String nn : ns){
                        none=v.equals(nn);
                        if(!none)break;
                    }
                }
                if (jnn.get(i).get("logic").asInt()==1){//与上一个并且
                    if(jnn.get(i).get("judge").asInt()==1){//有值
                        a=(byte)((!none && (a == -1 || a == 1))?1:0);
                    }else{//无值
                        a=(byte)((none && (a == -1 || a == 1))?1:0);
                    }
                }else{//与上一个或者
                    if(jnn.get(i).get("judge").asInt()==1){//有值
                        a=(byte)((!none || a == 1)?1:0);
                    }else{//无值
                        a=(byte)((none || a == 1)?1:0);
                    }
                }
            }
            return a==-1?0:a;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
    private String queryJsonForProgram(String key,Document body) {
        NodeList nl=body.getElementsByTagName("Streams");
        if(nl.getLength()==0)return "";
        return queryName(key,nl.item(0));
    }
    private String queryName(String name,Node doc){
        NodeList nl=doc.getChildNodes();
        if(nl.getLength()==0){
            if(doc.getNodeType()!=Node.ELEMENT_NODE)return null;
            Element e= (Element) doc;
            if(e.hasAttribute("name")){
                if(e.getAttribute("name").equals(name))return e.getNodeValue();
            }
            return null;
        }
        for(int i=0;i< nl.getLength();i++){
            String a=queryName(name,nl.item(i));
            if(a!=null)return a;
        }
        return null;
    }
    private void addTestState(String name){
        if(name.equals("小猪"))return;
        if(data.containsKey(name)){//存在
            Random ran=new Random();
            ArrayList<entEquipmentState> da=data.get(name);
            entEquipmentState e=da.get(da.size()-1);
            entEquipmentState s=new entEquipmentState(name,System.currentTimeMillis(), e.getAlarmState(),e.getProcessState(),e.getAwaitState(),e.getProgram(),e.getSpeed());
            if(e.getAwaitState()==0 && e.getProcessState()==0){//概率开机
                if(ran.nextInt(100)>50)s.setAwaitState(1);
                System.out.println(1);
                System.out.println(s);
            }else if((e.getAwaitState()==1 || e.getProcessState()==1)&& e.getAlarmState()==0){//概率警报
                if(ran.nextInt(100)>90){
                    s.setAlarmState(1);
                    s.setProgram("不知道程序叫啥名字");
                    s.setSpeed("null");
                }
                System.out.println(2);
                System.out.println(s);
            }else if(e.getAwaitState()==1){//概率运行
                if(ran.nextInt(100)>50){
                    s.setProcessState(1);
                    s.setAwaitState(0);
                    s.setProgram("不知道程序叫啥名字");
                    s.setSpeed("20转/min");
                }
                System.out.println(3);
                System.out.println(s);
            }else if(e.getProcessState()==1&&e.getAlarmState()==0){//概率停止运行
                if(ran.nextInt(100)>30){
                    s.setProgram("不知道程序叫啥名字");
                    s.setSpeed((ran.nextInt(10)+20)+"转/min");
                }
                System.out.println(3);
                System.out.println(s);
            }
            System.out.println("=");
            System.out.println(s);
            da.add(s);
            toolEquipmentState.add(s);
        }else{//不存在
            entEquipmentState s=new entEquipmentState(name,System.currentTimeMillis(), (byte) 0, (byte) 0, (byte) 0,"","");
            ArrayList<entEquipmentState> as=new ArrayList<>();
            as.add(s);
            data.put(name,as);
            toolEquipmentState.add(s);
        }
    }
}
